package accountmanager;

import java.io.File;
import java.util.Vector;

import accountmanager.accounts.*;

/**
 * 
 * AccountFactory is used to create new Accounts. Upon instantiation, AccountFactory finds the .class files for
 * all Accounts in ./classes/accountManager/accounts/ . It provides access to the Account types via getAccountNames().
 * 
 * @author Eric
 * @version 1.0
 */

public class AccountFactory {

	/**Path to the DrawShapes files (including trailing "/") */
	String path;

	/**Account class name list (stored as strings). Does not include package prefix.*/
	Vector<String> accountNames;

	/**
	 * Default constructor. The Account class name list is built from files in ./classes/accountmanager/accounts/ .
	 * File.separator makes pathname compatible accross OS's
	 */
	public AccountFactory() {
		String s = File.separator;
		init("."+s+"bin"+s+"accountmanager"+s+"accounts"+s);
	}

	/**
	 * Allows Account class name list to be built from files in a specified directory.
	 * 
	 * @param path
	 * 	Path to the Account files (including trailing "/")
	 */
	public AccountFactory(String path) {
		init(path);
	}

	/**
	 * Loads Account files and populates the accountNames list.
	 * 
	 * @param path
	 * Path to the Account files (including trailing "/")
	 */
	private void init(String path) {
		Class c = null;
		Object o = null;
		String className = "";

		try {
			this.path = path;

			// Build the accountNames list
			accountNames = new Vector<String>();
			File file = new File(path);
			String[] filenames = file.list(); // Get directory listing
			for (int i = 0; i < filenames.length; i++) { // Go through all files
				if (filenames[i].endsWith(".class") == true) { // Ignore if not a Java .class file
					if (filenames[i].compareTo("Account.class") != 0) { // Skip the Account base class
						// Try to load the class
						try {
							// Strip ".class" from the end
							className = filenames[i].substring(0, filenames[i].length() - 6);

							// Load the class and create an instance of it
							c = Class.forName("accountmanager.accounts." + className);
							o = c.newInstance();
						} catch (Exception ex) {
							ex.printStackTrace();
						}

						// Verify that it is a Account. If so, add its class name to the
						// shape list.
						if (o instanceof Account) {
							accountNames.addElement(className);
						}
					}
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**Returns a Vector of account class names*/
	public Vector<String> getAccountNames() {
		return (Vector<String>) accountNames.clone();
	}

	/**
	 * Create an instance of the specified account.
	 * 
	 * @param accountName
	 * Class name of the accout to create (without package prefix and .class suffix.
	 * @return The new Account
	 * @throws Exception
	 */
	public Account createAccount(String accountName) throws Exception {
		try {
			Class c = Class.forName("accountmanager.accounts." + accountName);
			Account a = (Account) c.newInstance();
			return a;
		} catch (Exception ex) {
			throw ex;
		}
	}
}
